"""
Assembly Module

This module provides the Assembly class which manages a collection of models in the BeaverFramework.
It handles the setup, execution, and coordination of multiple models in a wind turbine simulation.

Authors:
    MicahelZhang

Usage:
    assembly = Assembly("main_assembly")
    assembly.add_model(some_model)
    assembly.setup()
    assembly.run()
"""

class Assembly:
    """
    A class to manage and coordinate multiple models in a wind turbine simulation.
    
    The Assembly class serves as a container and coordinator for multiple simulation models.
    It ensures proper setup and sequential execution of all contained models, managing
    the flow of data between them.

    Attributes:
        name (str): Unique identifier for the assembly
        models (list): List of model objects contained in this assembly
    """

    def __init__(self, name):
        """
        Initialize a new Assembly instance.

        Args:
            name (str): Unique identifier for the assembly
        """
        self.name = name
        self.models = []

    def add_model(self, model):
        """
        Add a model to the assembly.

        Args:
            model: Model object to be added to the assembly.
                  Must implement setup(), update_inputs(), compute(), and update_outputs() methods.
        """
        self.models.append(model)

    def setup(self):
        """
        Set up all models in the assembly.
        
        Calls the setup() method on each model in the order they were added.
        This method should be called after all models have been added and before running the simulation.
        """
        for model in self.models:
            model.setup()

    def run(self):
        """
        Execute all models in the assembly.

        For each model in the assembly, this method:
        1. Updates input variables from other models
        2. Performs the model's computations
        3. Updates output variables for other models to use

        The execution happens in the order the models were added to the assembly.
        """
        for model in self.models:
            model.update_inputs()
            model.compute()
            model.update_outputs()
